(function() {
  define(['validate'], function() {
    'use strict';
    /*
    Extendendo o prototype do $.validator
    */

    var _this = this;
    $.extend($.validator.prototype, {
      /*
      Retorna o elemento para exibição do sumário de erro presente no formulário
      @return {$} jQuery object com o elemento presente no formulário.
      */

      getErrorSummary: function() {
        return $(this.currentForm).find('.error-summary');
      }
    });
    $.extend($.validator.messages, {
      required: 'Campo obrigat&oacute;rio',
      remote: 'Por favor, corrija este campo',
      email: 'Forne&ccedil;a um email v&aacute;lido',
      url: 'Forne&ccedil;a uma URL v&aacute;lida',
      date: 'Forne&ccedil;a uma data v&aacute;lida',
      dateISO: 'Forne&ccedil;a uma data v&aacute;lida (ISO)',
      dateITA: 'Forne&ccedil;a uma data v&aacute;lida',
      number: 'Forne&ccedil;a um n&uacute;mero v&aacute;lido',
      digits: 'Forne&ccedil;a somente d&iacute;gitos',
      creditcard: 'Forne&ccedil;a um cart&atilde;o de cr&eacute;dito v&aacute;lido',
      equalTo: 'Forne&ccedil;a o mesmo valor que o campo anterior.',
      accept: 'Forne&ccedil;a um valor com uma extens&atilde;o v&aacute;lida',
      alphanumeric: 'Forne&ccedil;a apenas letras ou números',
      maxlength: $.validator.format('Forne&ccedil;a n&atilde;o mais que {0} caracteres'),
      minlength: $.validator.format('Forne&ccedil;a ao menos {0} caracteres'),
      minWords: $.validator.format('Forne&ccedil;a ao menos {0} palavras'),
      rangelength: $.validator.format('Forne&ccedil;a um valor entre {0} e {1} caracteres de comprimento'),
      range: $.validator.format('Forne&ccedil;a um valor entre {0} e {1}'),
      max: $.validator.format('Forne&ccedil;a um valor menor ou igual a {0}'),
      min: $.validator.format('Forne&ccedil;a um valor maior ou igual a {0}'),
      summary: $.validator.format('Seu formulário contém {0} {1}, verifique os detalhes acima'),
      error_singular: 'erro',
      error_plural: 'erros'
    });
    $.validator.setDefaults({
      validClass: 'has-success',
      errorClass: 'has-error',
      /*
      Método que faz a tratativa para exibição de erros no
      formulário sendo validado.
      
      @param  {[type]} errorMap  [description]
      @param  {[type]} errorList [description]
      @return {[type]}           [description]
      */

      showErrors: function(errorMap, errorList) {
        return this.defaultShowErrors();
      },
      /*
      Método que determina onde a mensagem de erro deve aparecer.
      
      @param  {[type]} error   [description]
      @param  {[type]} element [description]
      @return {[type]}         [description]
      */

      errorPlacement: function(error, element) {
        var formGroup;
        error.addClass('help-block');
        formGroup = element.closest('.form-group');
        if (!formGroup.find('label.help-block.has-error, label.help-block.has-success').length) {
          return error.appendTo(element.closest('.form-group'));
        }
      },
      /*
      Marca o campo com erro.
      
      @param  {[type]} element    [description]
      @param  {[type]} errorClass [description]
      @param  {[type]} validClass [description]
      @return {[type]}            [description]
      */

      highlight: function(element, errorClass, validClass) {
        return $(element).closest('.form-group').addClass(errorClass).removeClass(validClass);
      },
      /*
      Limpa o campo com erro e marca o campo como validado.
      
      @param  {[type]} element    [description]
      @param  {[type]} errorClass [description]
      @param  {[type]} validClass [description]
      @return {[type]}            [description]
      */

      unhighlight: function(element, errorClass, validClass) {
        var $errorLabel, $formGroup;
        $formGroup = $(element).closest('.form-group');
        $errorLabel = $formGroup.find('.help-block.has-error');
        if (!$errorLabel.length || $errorLabel.is(':hidden')) {
          return $formGroup.removeClass(errorClass).addClass(validClass);
        }
      }
    });
    /*
    [setValidationRules description]
    */

    $.fn.extend({
      setValidationRules: function(rules) {
        return $(this).data('validation-rules', rules);
      }
    });
    $.validator.addMethod('letras_e_numeros', function(value) {
      var patt;
      patt = new RegExp("^(?=.*[a-zA-Z])(?=.*[0-9])");
      return patt.test(value);
    }, 'Necessário conter letras e números.');
    $.validator.addMethod('cep', function(value) {
      var objER;
      objER = new RegExp("^[0-9]{2}[0-9]{3}-[0-9]{3}");
      value = value.replace(/^s+|s+$/g, '');
      if (value.length > 0) {
        if (objER.test(value)) {
          return true;
        } else {
          return false;
        }
      } else {
        return blnVazio;
      }
    }, 'CEP Inválido.');
    $.validator.addMethod('cpf', function(cpf) {
      var add, i, rev;
      cpf = cpf.replace(/\./g, '');
      cpf = cpf.replace('-', '');
      if (cpf.length !== 11 || cpf === "00000000000" || cpf === "11111111111" || cpf === "22222222222" || cpf === "33333333333" || cpf === "44444444444" || cpf === "55555555555" || cpf === "66666666666" || cpf === "77777777777" || cpf === "88888888888" || cpf === "99999999999") {
        return false;
      }
      add = 0;
      i = 0;
      while (i < 9) {
        add += parseInt(cpf.charAt(i)) * (10 - i);
        i++;
      }
      rev = 11 - (add % 11);
      if (rev === 10 || rev === 11) {
        rev = 0;
      }
      if (rev !== parseInt(cpf.charAt(9))) {
        return false;
      }
      add = 0;
      i = 0;
      while (i < 10) {
        add += parseInt(cpf.charAt(i)) * (11 - i);
        i++;
      }
      rev = 11 - (add % 11);
      if (rev === 10 || rev === 11) {
        rev = 0;
      }
      if (rev !== parseInt(cpf.charAt(10))) {
        return false;
      }
      return true;
    }, 'CPF Inválido');
    return $.validator.addMethod('cnpj', function(cnpj) {
      var digitos, i, numeros, pos, resultado, soma, tamanho;
      cnpj = cnpj.replace(/[^\d]+/g, "");
      if (cnpj === "") {
        return false;
      }
      if (cnpj.length !== 14) {
        return false;
      }
      if (cnpj === "00000000000000" || cnpj === "11111111111111" || cnpj === "22222222222222" || cnpj === "33333333333333" || cnpj === "44444444444444" || cnpj === "55555555555555" || cnpj === "66666666666666" || cnpj === "77777777777777" || cnpj === "88888888888888" || cnpj === "99999999999999") {
        return false;
      }
      tamanho = cnpj.length - 2;
      numeros = cnpj.substring(0, tamanho);
      digitos = cnpj.substring(tamanho);
      soma = 0;
      pos = tamanho - 7;
      i = tamanho;
      while (i >= 1) {
        soma += numeros.charAt(tamanho - i) * pos--;
        if (pos < 2) {
          pos = 9;
        }
        i--;
      }
      resultado = (soma % 11 < 2 ? 0 : 11 - soma % 11);
      if (resultado !== parseInt(digitos.charAt(0))) {
        return false;
      }
      tamanho = tamanho + 1;
      numeros = cnpj.substring(0, tamanho);
      soma = 0;
      pos = tamanho - 7;
      i = tamanho;
      while (i >= 1) {
        soma += numeros.charAt(tamanho - i) * pos--;
        if (pos < 2) {
          pos = 9;
        }
        i--;
      }
      resultado = (soma % 11 < 2 ? 0 : 11 - soma % 11);
      if (resultado !== parseInt(digitos.charAt(1))) {
        return false;
      }
      return true;
    }, 'CNPJ Inválido');
  });

}).call(this);
